<?php
namespace Cyfy\Modules\DibiPager;

/**
 * Module for creating DB queries with pages.
 *
 * @author Dandelion
 * @version 0.1
 */

class DibiPager extends \Cyfy\Translatable
{
    /** 
     * How many entries on page by default.
     */
    const DEFAULT_ON_PAGE = 10;
    
    /**
     * Whether has DibiPager run.
     * @var bool
     */
    static private $hasRun = false;
    
    
    /**
     * Name of the module to be called by AJAX.
     * @var string
     */
	private $ajaxModule = "";
    
    /**
     * Name of the ajax callback to be called when clicked on page.
     * @var string
     */
	private $ajaxName = "";
    
    /**
     * jQuery selector of place the content is in. Usually something like #objectId.
     * @var string 
     */
	private $ajaxPlace = "";
    
    /**
     * Custom POST parameters in string.
     * @var string 
     */
	private $ajaxSend = "";
    
    /**
     * Pager cache. Once pager generated, this variable contents generated pager.
     * @var string
     */
    private $pagerContent = "";
    
    /**
     * Query with the pager is called. Must be without LIMIT part. Can be array only when in combination with custom pager query.
     * @var mixed
     */
    private $query = '';
    
    /**
     * Name of the pager. Must be only letters, without spaces.
     * @var string
     */
    private $pagerName = '';
  
    /**
     * Sort form. Must be created with custom structure paramerer.
     * Eg. new \Cyfy\Modules\DibiPager\Forms\SortBy(true);
     */
    public $sortForm = null; 
  
    /**
     * Creates a Dibi Pager
     * 
     * @param string Name of the pager.
     * @param int How many entries on one page.
     */
    public function __construct($pagerName = '', $onpage = 0)
    {
        if ($pagerName == '')
        {
            $pagerName = uniqid();
        }
        
        $this -> pagerName = $pagerName;
        
        // if some custom onpage settings
        if ($onpage)
        {
            $_SESSION["pagerOnPage"][$pagerName] = $onpage;      
        }
        elseif ($_SESSION["pagerOnPage"][$pagerName] == 0)
        {
            $_SESSION["pagerOnPage"][$pagerName] = self :: DEFAULT_ON_PAGE;
        }
    }
	
    /**
     * Sets called ajax function.
     *
     * @param string Module name
     * @param string Ajax method name
     * @param string Place where data is inserted. Usually '#something'
     * @param string Custom POST parameters in string
     */
    public function ajaxCall($module, $name, $place, $send = "")
    {
        $this -> ajaxModule = $module;
        $this -> ajaxName = $name;
        $this -> ajaxPlace = $place;
        $this -> ajaxSend = $send;
    }
  
    /**
     * Sends a new query with posibility of paging.
     *
     * @param string Standart mysql query, but !!!! WITHOUT: LIMIT !!!! and MUST CONTAIN THIS PART: "SELECT ...something... FROM"
     * @return dibi results
     */  
	public function query($query)
    {
        $this -> query = $query;
        
		// maximum on page
        $max = ($_SESSION["pagerOnPage"][$this -> pagerName]) ? $_SESSION["pagerOnPage"][$this -> pagerName] : (self :: DEFAULT_ON_PAGE);
        
        // get/post limit
        if($_REQUEST["limit"]){
            $limit = $_REQUEST["limit"];
        }else{
            $limit = 0;
        }
        
        $limits = '';
        // if session order by
        if($_SESSION["sort-by"][$this -> pagerName])
        {
            if(!$_SESSION["sort-how"][$this -> pagerName]){
                $_SESSION["sort-how"][$this -> pagerName] = "ASC";
            }
            $limits .= " ORDER BY {$_SESSION["sort-by"][$this -> pagerName]} {$_SESSION["sort-how"][$this -> pagerName]}";
        }

        // start limiting
        $start = $limit * $max;
        $limits .= " LIMIT {$start},{$max}";		
        return \dibi :: query(func_get_args(), $limits);
    }
	 
    /**
     * Gets a list of pages with links on each item.
     *
     * If you call it with $customQuery parameter, the number of pages will be extracted from that. It's recommended, if you use long queries.
     * If called with no parameter, then it is extracted from $query.
     *
     * @param  string Query for getting number of pages. Egq
     * @return string List of pages with links
     */
    public function pager($customQuery = '')
    {
       // cached?
        if($this -> pagerContent)
        {
            return $this -> pagerContent;
        }
        
        // if no query
        if($this -> query == "" && $customQuery == "")
        {
            return false;
        }
        
        
        // called with query?
        if($customQuery=='')
        {   
            if(is_array($this -> query))
            {
                return "Error - query can't be array";
            }
            // replacing SELECT something FROM
            $pattern = '/SELECT (.*) FROM/';
            $replacement = 'SELECT count(*) FROM';
            $customQuery = preg_replace($pattern, $replacement, $this -> query);
            // OLD $query = strtr($this -> query, array("SELECT * FROM" => "SELECT count(*) FROM"));
        }
        
        
        // include_once javascripts
        self :: runonce();
                
        // add to the header - because when URL with #this part
        $js = <<<JAVASCRIPT
$(document).ready(function(){    var hash = window.location.hash;    if(hash){        hash = hash.substr(1);        var dashpos = hash.lastIndexOf("-");        if(dashpos){            if(hash.substr(0, dashpos) == "{$this->pagerName}"){                var limit = hash.substr(dashpos + 1);                if(limit != '0') Pager.loadPage('{$this -> ajaxModule}','{$this -> ajaxName}', '{$this -> ajaxPlace}', '{$this -> ajaxSend}', '{$this -> pagerName}', limit);            }        }    }});
JAVASCRIPT;
        \Cyfy\Cyfy ::  javaScript($js, "inline", "header");
        
        // maximum on page
        $max = ($_SESSION["pagerOnPage"][$this -> pagerName]) ? $_SESSION["pagerOnPage"][$this -> pagerName] : DB_PAGER_NUM;
        // get/post limit
        if($_REQUEST["limit"]){
                $limit = $_REQUEST["limit"];
            }else{
                $limit = 0;
        }
        
        // counting pages
        $nums = \dibi :: query($customQuery) -> fetchSingle();
        if($nums == 0) return "";
        for($i=1;$i < (($nums / $max) + 1);$i++)
        {
                $active = ($limit == $i-1) ? true : false;
                $this -> pages[] = array("number"=>$i, "active"=>$active, "link" => $i - 1);
        }
        $onclick = "";
        
        $output = "<div class=\"pagerClear\"></div>\n";
        $output .= "<ul class=\"pager pager_{$this->pagerName}\">\n";
        foreach($this -> pages as $p)
        {
        // Is this page active?
            $cls = "page_" . $p["link"];
            if($p["active"]){
                $cls .= " active";
            }
            $output .= "  <li class=\"{$cls}\"><a href=\"?limit={$p["link"]}\" onclick=\"Pager.loadPage('{$this -> ajaxModule}','{$this -> ajaxName}', '{$this -> ajaxPlace}',  '{$this -> ajaxSend}', '{$this-> pagerName}', '{$p["link"]}'); Cyfy.redirectToOutside('#{$this->pagerName}-".$p["link"]."'); return false;\">{$p["number"]}</a></li>\n";
        }
        $output .= "</ul>\n";
        $output .= "<div class=\"pagerClear\"></div>\n";
        $this -> pagerContent = $output;
        return $output;
	}

    /**
     * Returns sorting form, which must be created.
     * @return string HTML content
     */
	public function showSortForm()
    {
        if(!$this->sortForm)
        {
            return false;
        }
        
        // settings
        $this -> sortForm -> setTemp("pagerName", $this -> pagerName);
        $this -> sortForm -> setTemp("onSubmit", "Pager.loadPage('{$this -> ajaxModule}','{$this -> ajaxName}', '{$this -> ajaxPlace}', '', '{$this -> pagerName}', '0');");
        $this -> sortForm -> onPageDefault = self :: DEFAULT_ON_PAGE;
        $this -> sortForm -> structure();
        $this -> sortForm -> setData(array("onPage" => $_SESSION["pagerOnPage"][$this -> pagerName]));
        
        $c = new \Cyfy\Modules\Objects\Collapsible();
        $c -> setData(self :: t(10), $this -> sortForm -> show(), true);   
        return $c -> show();
    }
    
	/*
	 * Runonce, when pager active. Sets scripts to the header
	 * 
	 */
    static private function runonce()
    {
        if(!self :: $hasRun){
            self :: $hasRun = true;   
            \Cyfy\Cyfy ::  javaScript(\Cyfy\Cyfy ::  getSourcePath("Cyfy/Modules/DibiPager/dibi-pager.js"), "file");
            \Cyfy\Cyfy ::  CSS(\Cyfy\Cyfy ::  getSourcePath("Cyfy/Modules/DibiPager/pager.css"));
        }        
    }
    
    
}

